<template>
  <div class="customer">
    <van-nav-bar
      title="客服消息"
      class="nav_bar"
      fixed
      @click-left="onClickLeft"
    >
    </van-nav-bar>
    <div class="main" ref="scrollContainer" :style="{ height: mainHeight }">
      <van-pull-refresh
        v-model="refreshing"
        disabled
        @refresh="onRefresh"
        pulling-text="加载更多历史消息"
        loading-text="请稍等"
        loosing-text="下拉即可加载更多"
      >
        <van-list v-model="loading" :finished="finished" finished-text="">
          <div
            v-for="(v, i) in list"
            :key="JSON.stringify(v) + i"
            class="chat_container"
          >
            <div v-if="shouldShowTime(v, i)" class="time">
              {{ formatChatTime(v.createTime) }}
            </div>
            <div
              class="chat_item"
              :class="{ system: v.sendType == 3, user: v.sendType == 1 }"
            >
              <van-image
                class="avatar"
                fit="cover"
                round
                :src="
                  v.sendType == 3
                    ? require('@/assets/icon/common/avatar_2.png')
                    : v.sendUserAvatar
                "
              />
              <div class="right">
                <div class="username">
                  {{ v.sendType == 3 ? "客服" : "我" }}
                </div>
                <div v-if="v.type == 0" class="message">
                  <div class="text_2">
                    {{ v.text }}
                  </div>
                </div>
                <div v-if="v.type == 1" class="message">
                  <van-image
                    class="message_pic"
                    @click="imagePreview(v.fileUrl)"
                    @load="scrollToBottom()"
                    :src="v.fileUrl"
                  >
                    <template #loading>
                      <van-loading type="spinner" size="20" />
                    </template>
                  </van-image>
                </div>
              </div>
              <van-loading v-if="v.loading" />
            </div>
          </div>
        </van-list>
      </van-pull-refresh>
    </div>
    <div class="input_container">
      <div class="input">
        <van-icon name="add-o" class="input_add" @click="picShow" />
        <van-search
          v-model="message"
          show-action
          placeholder="请输入您想咨询的内容"
        >
          <template #action>
            <div @click="onSend" class="search_btn">发送</div>
          </template>
        </van-search>
      </div>
      <div class="other_container" :class="{ add_active: showPic }">
        <van-uploader
          max-count="1"
          :preview-image="false"
          :after-read="afterRead"
        >
          <van-grid :border="false">
            <van-grid-item icon="photo-o" text="相册" />
          </van-grid>
        </van-uploader>
      </div>
    </div>
  </div>
</template>

<script>
import api from "@/api/api";
import { ImagePreview, Toast } from "vant";
import { mapGetters } from "vuex";
import { vw } from "@/utils/common";

export default {
  components: {},
  props: {},
  data() {
    return {
      list: [],
      loading: false,
      finished: true,
      refreshing: false,
      message: "",
      showPic: false,
      fileList: [],
      pageInfo: {
        pageNum: 1,
        pageSize: 20,
      },
      sendFlag: false,
      timer: null,
    };
  },
  watch: {},
  computed: {
    ...mapGetters(["userData"]),
    mainHeight() {
      if (this.showPic) {
        return `calc(100vh - ${vw(47)} - ${vw(160)})`;
      }
      return `calc(100vh - ${vw(47)} - ${vw(80)})`;
    },
  },
  methods: {
    onClickLeft() {
      this.$router.back();
    },
    picShow() {
      if (this.sendFlag) return;
      this.showPic = !this.showPic;
      setTimeout(() => {
        this.scrollToBottom();
      }, 200);
    },
    onLoad() {
      if (this.refreshing) {
        this.list = [];
        this.refreshing = false;
      }
      this.getMessageList();
    },
    onRefresh() {
      // 清空列表数据
      this.refreshing = true;
      // 重新加载数据
      // 将 loading 设置为 true，表示处于加载状态
      this.loading = true;
      this.onLoad();
    },
    // 时间间隔判断（小于1分钟不显示）
    shouldShowTime(currentMsg, index) {
      if (index === 0) return true;
      let prevTime = new Date(this.list[index - 1].createTime).getTime();
      let currentDate = new Date(currentMsg.createTime).getTime();
      return currentDate - prevTime > 2 * 60 * 1000;
    },
    // 动态时间格式化
    formatChatTime(timestamp) {
      const now = new Date();
      const msgDate = new Date(timestamp);
      const diffDays = Math.floor((now - msgDate) / (1000 * 3600 * 24));

      // 规则判断
      if (msgDate.getFullYear() !== now.getFullYear()) {
        return this.formatDate(msgDate, "yyyy-MM-dd hh:mm");
      } else if (diffDays > 7) {
        return this.formatDate(msgDate, "MM-dd hh:mm");
      } else if (msgDate.toDateString() !== now.toDateString()) {
        return `${this.getWeekDay(msgDate)} ${this.formatDate(
          msgDate,
          "hh:mm"
        )}`;
      } else {
        return this.formatDate(msgDate, "hh:mm");
      }
    },
    // 通用日期格式化（参考优化方案[5](@ref)）
    formatDate(date, fmt) {
      const o = {
        "M+": date.getMonth() + 1,
        "d+": date.getDate(),
        "h+": date.getHours(),
        "m+": date.getMinutes(),
      };
      if (/(y+)/.test(fmt)) {
        fmt = fmt.replace(
          RegExp.$1,
          date.getFullYear().toString().slice(-RegExp.$1.length)
        );
      }
      for (const k in o) {
        const regex = new RegExp(`(${k})`);
        if (regex.test(fmt)) {
          fmt = fmt.replace(regex, (match) =>
            match.length === 1 ? o[k] : o[k].toString().padStart(2, "0")
          );
        }
      }
      return fmt;
    },

    // 获取星期（优化自[3](@ref)）
    getWeekDay(date) {
      const weekDays = ["日", "一", "二", "三", "四", "五", "六"];
      return `周${weekDays[date.getDay()]}`;
    },
    async onSend() {
      if (this.sendFlag) return;
      if (this.message.trim().length == 0) {
        Toast("不能发送空消息");
      } else {
        this.sendFlag = true;
        let params = {
          accountType: 0,
          storeId: 1,
          text: this.message,
          type: 0,
          fileUrl: "",
        };
        if (this.fileList.length) {
          params.type = 1;
        }
        this.list.push({
          userId: this.userData.id,
          storeId: params.storeId,
          sendType: 1,
          type: params.type,
          text: this.message,
          flleUrl: params.fileUrl,
          sendUserName: this.userData.userName,
          sendUserAvatar: this.userData.avatar,
          createTime: Date.now(),
          loading: true,
          dev: true,
        });
        setTimeout(() => {
          this.message = "";
        }, 200);
        this.scrollToBottom(); // 替换原有的$nextTick逻辑
        await api.sendMessage(params).finally(() => {
          this.list[this.list.length - 1].loading = false;
          this.sendFlag = false;
        });
      }
    },
    imagePreview(src) {
      ImagePreview([src]);
    },
    async afterRead(file) {
      let data = new FormData();
      data.append("file", file.file);
      let res = await api.upload(data);
      let params = {
        accountType: 0,
        storeId: 1,
        text: "",
        type: 1,
        fileUrl: res,
      };
      this.list.push({
        userId: this.userData.id,
        storeId: params.storeId,
        sendType: 1,
        type: params.type,
        text: this.message,
        flleUrl: params.fileUrl,
        sendUserName: this.userData.userName,
        sendUserAvatar: this.userData.avatar,
        createTime: Date.now(),
        loading: true,
        dev: true,
      });
      this.scrollToBottom();
      setTimeout(() => {
        this.showPic = !this.showPic;
      }, 200);
      await api.sendMessage(params).finally(() => {
        this.list[this.list.length - 1].loading = false;
        this.sendFlag = false;
      });
    },
    async getMessageList() {
      let parmas = {
        ...this.pageInfo,
        storeId: 1,
      };
      let res = await api.getMessageList(parmas);
      this.list = [...this.list, ...res.data].filter((item) => !item.dev);
      const uniqueMap = new Map(this.list.map((item) => [item.autoId, item]));
      this.list = Array.from(uniqueMap.values());
      this.scrollToBottom(); // 替换原有的$nextTick逻辑
      if (res.data.length < this.pageInfo.pageSize) {
        this.finished = true;
      } else {
        this.pageInfo.pageNum++;
        this.getMessageList();
      }
    },
    scrollToBottom() {
      this.$nextTick(() => {
        const container = this.$refs.scrollContainer;
        if (container.scrollHeight <= container.clientHeight) {
          return; // 内容不足一屏时不滚动
        }
        if (container) {
          // 获取容器实际样式（包含padding）
          const style = window.getComputedStyle(container);
          const paddingBottom = parseFloat(style.paddingBottom) || 0;

          // 计算正确的滚动位置（包含padding补偿）
          const scrollPosition =
            container.scrollHeight - container.clientHeight + paddingBottom;
          // 计算正确的滚动位置：滚动高度 - 容器可视高度 + 底部padding
          container.scrollTo({
            top: scrollPosition,
            behavior: "smooth",
          });
        }
      });
    },
  },
  created() {
    setTimeout(() => {
      this.timer = setInterval(() => {
        this.getMessageList();
      }, 10000);
    }, 10000);
  },
  mounted() {
    this.onLoad();
    if (/iOS/i.test(navigator.userAgent)) {
      this.$refs.input.$el.addEventListener("focus", () => {
        setTimeout(() => {
          window.scrollTo(0, document.body.sc);
        }, 300); // 等待键盘动画
      });
    }
  },
  beforeDestroy() {
    clearInterval(this.timer);
  },
};
</script>
<style lang="less" scoped>
.customer {
  min-height: 100vh;
  background: url("https://zxcxappimg.oss-cn-hangzhou.aliyuncs.com//zxcxmall/2025/05/29/4431a33cd62f4efc9fc53a7606eee382.png")
    no-repeat;
  background-size: cover;
  background-attachment: fixed;
  background-position: center;
  box-sizing: border-box;
  padding: 200px 50px 220px 50px;
  overflow: hidden;

  .nav_bar {
    /deep/ .van-icon {
      font-size: 50px;
      font-weight: bold;
      color: #333333;
    }
  }

  .main {
    // height: calc(100vh - 46px - 70px);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch; // iOS优化
    will-change: transform; // 硬件加速优化

    .chat_container {
      display: flex;
      flex-direction: column;

      .time {
        width: 100%;
        font-size: 44px;
        color: #333;
        text-align: center;
      }

      .chat_item {
        display: flex;
        align-items: start;
        width: 100%;
        margin: 40px 0;

        .avatar {
          min-width: 150px;
          max-width: 150px;
          height: 150px;
        }

        .right {
          .username {
            font-size: 45px;
            color: #888888;
            margin-bottom: 15px;
          }

          .message {
            padding: 30px 25px;
            border-radius: 20px;
            flex-grow: 1;

            .text_2 {
              font-size: 44px;
              color: #666666;
            }
          }

          .message_pic {
            max-width: 600px;
            object-fit: contain;
          }
        }
      }

      .system {
        justify-content: start;

        .right {
          margin-left: 30px;

          .message {
            background: #fff;
          }
        }
      }

      .user {
        flex-direction: row-reverse;

        .right {
          margin-right: 30px;

          .username {
            text-align: right;
          }

          .message {
            background: #406dfc;

            .text_2 {
              color: #fff;
            }
          }
        }
      }
    }
  }

  .input_container {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    padding: 30px 30px 90px 30px;
    background: #fff;
    z-index: 99;

    .input {
      display: flex;
      align-items: center;
      justify-content: space-between;

      .input_add {
        font-size: 60px;
        margin-right: 25px;
      }

      /deep/ .van-search {
        padding: 0;
        flex-grow: 1;
      }

      .search_btn {
        font-size: 38px;
        padding: 0 40px;
        background: #406dfc;
        border-radius: 10px;
        height: 100px;
        line-height: 100px;
        color: #fff;
      }
    }

    .other_container {
      width: 100%;
      height: 0;
      transition: all 1s;
      display: none;
    }

    .add_active {
      display: flex;
      height: 250px;
    }
  }
}
</style>
